home *** CD-ROM | disk | FTP | other *** search
/ One Click 14 / OneClick14.iso / Ferramentas / Convert XLS to Pdf / xls2pdf_setup.exe / {app} / lib / pdf_font.ps < prev    next >
Encoding:
Text File  |  2002-11-15  |  39.4 KB  |  1,225 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdf_font.ps,v 1.51 2002/11/14 21:22:22 alexcher Exp $
  14. % pdf_font.ps
  15. % PDF font operations.
  16.  
  17. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  18. .currentglobal true .setglobal
  19. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  20. GS_PDF_ProcSet begin
  21. pdfdict begin
  22.  
  23. % We cache the PostScript font in an additional element of the
  24. % font resource dictionary, called PSFont.
  25.  
  26. % ---------------- Encodings ---------------- %
  27.  
  28. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  29.  
  30. % Apply a list of differences to an Encoding.
  31. % Note that the differences may cause the array to grow.
  32. /updateencoding {    % <encoding|null> <differences> updateencoding <enc'>
  33.     % Calculate the length of the result.
  34.   % in case the incoming Encoding is null, use .notdefEncoding
  35.   exch dup null eq { pop .notdefEncoding } if
  36.   0 0 3 index {
  37.     dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse
  38.     % Differences list may not be in order, update the largest_index
  39.     % stack: <Differences> <encoding> <largest_index> <at_index>
  40.     2 copy lt { exch pop dup } if    % at_index is new largest
  41.   } forall
  42.   pop 1 index length .max array dup 0 4 -1 roll putinterval
  43.   exch 0 exch {
  44.         % Stack: enc' code element
  45.     dup type /nametype ne
  46.       { exch pop oforce }
  47.       { 3 copy put pop 1 add }
  48.     ifelse
  49.   } forall pop
  50. } bdef
  51.  
  52. % Get the Encoding for a font.
  53. /getencoding        % <base-encoding> <font-resource> getencoding <enc>
  54.  { /Encoding knownoget
  55.     { dup type /nametype eq
  56.        {
  57.          % The published PDF specification says the Encoding name
  58.          % "must be" one of the 3 predefined Encodings, implying
  59.          % that an error should occur if it isn't.  However, Acrobat
  60.          % Reader simply ignores unknown names, and since there are
  61.          % some buggy applications that rely on this, we do the same.
  62.  
  63.          dup dup dup /MacRomanEncoding eq
  64.          exch /MacExpertEncoding eq or 
  65.          exch /WinAnsiEncoding eq or
  66.            { exch pop findencoding
  67.            }
  68.            { pop
  69.            }
  70.          ifelse
  71.        }
  72.        { dup /BaseEncoding knownoget
  73.       { findencoding 3 -1 roll pop exch
  74.       }
  75.      if
  76.      /Differences knownoget { updateencoding } if
  77.        }
  78.       ifelse
  79.     }
  80.    if
  81.  } bdef
  82.  
  83. % Define a font using it's FontName as the key.
  84. % Adjust a font according to the Encoding and Widths in the font resource.
  85. /adjustfont {        % <font-resource> <font> adjustfont <font'>
  86.   getfontencoding
  87.   getfontmetrics 4 -1 roll pop .updatefont { dup /FontName get exch definefont } if
  88. } bind def
  89.  
  90. % Get the (possibly modified) encoding of a font.
  91. /getfontencoding {    % <font-resource> <font> getfontencoding
  92.             %   <font-resource> <font> <Encoding|null>
  93.   1 index /Encoding known {
  94.     dup /Encoding knownoget { 2 index getencoding } { null } ifelse
  95.   } {
  96.     null
  97.   } ifelse
  98. } bdef
  99.  
  100. % Returns true if the current glyph is in the Differences array at
  101. % the specified index value. This is needed because the Widths
  102. % array may map to the same glyph at different positions from the
  103. % Encoding. We want to use the Width that was associated with the
  104. % one specified in the Encoding::Differences list.
  105. /match_in_diff     % <Differences> <index> <glyphname> match_in_diff <bool>
  106. { false 4 1 roll 0 4 -1 roll    % stack: false index glyphname at_index==0 Differences
  107.   { exch 1 index type /nametype ne {
  108.       % stack: false index glyphname Diff_element at_index 
  109.       pop    % Diff_element is new at_index
  110.     } {
  111.       % stack: false index glyphname Diff_element at_index 
  112.       exch 2 index eq {
  113.         % stack: false index glyphname at_index 
  114.     dup 3 index eq {
  115.           true 5 1 roll    % stack: true false index glyphname at_index
  116.           pop exit
  117.         } if
  118.       } if
  119.       1 add        % at_index++ stack: false index glyphname at_index' 
  120.     } ifelse
  121.   } forall
  122.   % stack: true  false index     glyphname
  123.   %  or  : false index glyphname at_index
  124.   pop pop pop
  125. } bdef
  126.  
  127. % Get the metrics of a font, if specified.
  128. /getfontmetrics {    % <font-resource> <font> <Encoding|null> getfontmetrics
  129.             %   <font-resource> <font> <Encoding|null>
  130.             %   <Metrics|null>
  131.   2 index /Widths known {
  132.     dup null eq { pop dup /Encoding get } if
  133.     4 dict begin
  134.       /Encoding exch def
  135.       /Metrics Encoding length dict def
  136.       exch
  137.       dup /Widths oget /Widths exch def
  138.         % Stack: font font-res
  139.         % Note that widths are always based on a 1000-unit
  140.         % character space, but the FontMatrix may specify
  141.         % some other scale factor.  Compensate for this here,
  142.         % by scaling the Widths if necessary.
  143.       0.001 2 index /FontMatrix get 0 get div
  144.         % Stack: font font-res mscale
  145.       1 index /FirstChar oget dup 1 4 index /LastChar oget
  146.        {    % Stack: font font-res mscale first-char index
  147.      Encoding 1 index dup 2 index length ge {
  148.            (   **** Warning: Font Encoding array size is smaller than character range.\n)
  149.            pdfformaterror
  150.        pop pop /.notdef
  151.          } {
  152.        get
  153.      } ifelse
  154.      Widths 2 index 4 index sub dup 2 index length ge {
  155.            (   **** Warning: Font Widths array size is smaller than character range.\n)
  156.            pdfformaterror
  157.            % use MissingWidth if it's available, if not, default to 1000 (full width)
  158.        pop pop 4 index /FontDescriptor knownoget {
  159.          /MissingWidth knownoget not { 1000    } if
  160.        } { 1000 } ifelse
  161.          } {
  162.        get
  163.      } ifelse
  164.          % Stack: font font-res mscale first-char index charname width
  165.      4 index mul
  166.         % The following 'loop' is only context for 'exit'.
  167.      {    
  168.         % Work around a bug in pdfTeX, which can generate Encoding
  169.         % vectors containing nulls :
  170.        1 index null eq { exit } if
  171.         % There is a hack here to deal with encodings where the
  172.         % same character appears more than once, because the Metrics
  173.         % dictionary works by character name, not by character code.
  174.         % We prefer to take (1) non-zero width, and (2) width for 
  175.         % the character name which appears in Differences. If the
  176.         % character name appears in Differences, use the Width that
  177.         % corresponds to the index in differences.
  178.        dup 0 eq { exit } if
  179.        Metrics 2 index .knownget not { 0 } if 0 ne {
  180.          5 index /Encoding knownoget not { exit } if
  181.          dup type /dicttype ne { pop exit } if
  182.          /Differences knownoget not { exit } if
  183.          3 index 3 index //match_in_diff exec not { exit } if
  184.        } if
  185.        2 copy Metrics 3 1 roll put
  186.        exit
  187.      } loop
  188.      pop pop pop
  189.        }
  190.       for pop
  191.         % Now fill in the MissingWidth for any encoded characters
  192.         % that aren't in Metrics already.  Note that built-in
  193.         % fonts may have Widths/FirstChar/LastChar but no
  194.         % FontDescriptor, so we must check for this.
  195.         % Stack: font font-res mscale
  196.       1 index /FontDescriptor knownoget {
  197.     Metrics exch
  198.     /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  199.     Encoding {
  200.         % Stack: font font-res mscale missing-width metrics charname
  201.         % Work around the abovementioned pdfTeX bug.
  202.       dup null ne {
  203.         2 copy known not { 2 copy 4 index put } if pop
  204.       } {
  205.         pop
  206.       } ifelse
  207.     } forall pop pop pop
  208.       } {
  209.     pop
  210.       } ifelse
  211.     exch Encoding Metrics end
  212.   } {
  213.     null
  214.   } ifelse
  215. } bdef
  216.  
  217. currentdict /match_in_diff undef
  218.  
  219. % ---------------- Descriptors ---------------- %
  220.  
  221. % Partial descriptors for the 14 built-in fonts.  Note that
  222. % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
  223. % object has undergone a subtle change in its meaning which has serious
  224. % consequences for searching with Acrobat:
  225. % In PDF 1.1, the flag meant: Font has StandardEncoding
  226. % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
  227. /standardfontdescriptors mark
  228.   /Courier mark /Flags 16#23 .dicttomark
  229.   /Courier-Oblique 1 index
  230.   /Courier-Bold 1 index
  231.   /Courier-BoldOblique 1 index
  232.   /Helvetica mark /Flags 16#20 .dicttomark
  233.   /Helvetica-Oblique 1 index
  234.   /Helvetica-Bold 1 index
  235.   /Helvetica-BoldOblique 1 index
  236.   /Times-Roman mark /Flags 16#22 .dicttomark
  237.   /Times-Bold 1 index
  238.   /Times-Italic mark /Flags 16#62 .dicttomark
  239.   /Times-BoldItalic 1 index
  240.   /Symbol mark /Flags 16#4 .dicttomark
  241.   /ZapfDingbats 1 index
  242. .dicttomark readonly def
  243.  
  244. % ---------------- Utilities ---------------- %
  245.  
  246. /.pdforigfontcache_g 20 dict def
  247. currentglobal false setglobal
  248. systemdict /.pdforigfontcache_l 20 dict .forceput
  249. setglobal
  250.  
  251. % Cache original fonts to prevent adjustfont to accumulate changes.
  252. /pdfcachefont {   % <font_name> pdfcachefont <font>
  253.   dup //.pdforigfontcache_g exch .knownget {
  254.     exch pop
  255.   } {
  256.     dup .pdforigfontcache_l exch .knownget {
  257.       exch pop
  258.     } {
  259.       dup findfont dup    
  260.       dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse
  261.                      % Stack : font_name font font cache
  262.       4 2 roll .growput
  263.     } ifelse
  264.   } ifelse
  265. } bind def
  266.  
  267. % Find a font (except for embedded ones), and adjust its encoding if necessary.
  268. /.pdfdfndict mark
  269.   /defaultfontname /Helvetica
  270. .dicttomark readonly def
  271. /pdffindfont {        % <font-resource> <fontname> pdffindfont <font>
  272.         % If the font isn't available, synthesize one based on
  273.         % its descriptor.
  274.   dup /Font resourcestatus {
  275.     pop pop pdfcachefont
  276.   } {
  277.     1 index /FontDescriptor knownoget {
  278.         % Stack: font-res fontname fontdesc
  279.       dup /Flags oget
  280.       dup 16#40 and -6 bitshift        % 1, oblique/italic
  281.       1 index 16#40000 and -17 bitshift add    % 2, bold
  282.       exch 16#2 and 2 bitshift add    % 8, serif
  283.         % We should look at the fixed flag, too.
  284.         % Stack: font-res fontname fontdesc properties
  285.  
  286.                 % Even though /FontName is a required key in FontDescriptor dict
  287.                 % (As of the PDF 1.4 Reference Manual), In the case of missing 
  288.                 % /FontName key, we substitue /BaseFont for the value of /FontName.
  289.                 % Yet another case of broken PDF's that Adobe Reader accepts.
  290.       1 index dup /FontName known {
  291.         /FontName oget exch
  292.       } {
  293.         (   **** FontDescriptor missing required /FontName key. BaseFont name used.\n)
  294.         pdfformaterror
  295.         pop 2 index exch    % grab the BaseFont from the stack.
  296.       } ifelse
  297.         % Analyzes font name and extract "Narrow" property
  298.         % which is not described by the FontDescriptor Flags.
  299.       0 2 index .fontnameproperties 4 and or
  300.         % Rebind the default font name to Helvetica so that
  301.         % fonts with no properties are handled correctly.
  302.       //.pdfdfndict begin .substitutefontname end
  303.         % Stack: font-res fontname fontdesc substname|null
  304.       Fontmap 1 index known not {
  305.         % No available good substitution, use the standard one.
  306.     pop 1 index .substitutefont
  307.       } if
  308.       dup 3 index ne QUIET not and {
  309.     (Substituting font ) print dup =only
  310.     ( for ) print 2 index =only (.) = flush
  311.       } if
  312.       pdfcachefont
  313.         % Stack: font-res fontname fontdesc font
  314.         % If this is a small-caps font, replace the CharString
  315.         % entries for a..z.
  316.       exch /Flags oget 16#20000 and 0 ne {
  317.     true .copyfontdict
  318.     dup /CharStrings 2 copy get dup length dict .copydict
  319.     4 index /FirstChar get 97 .max
  320.     5 index /LastChar get 122 .min 1 exch {
  321.         % Stack: font-res font' font' /CharStrings charstrings code
  322.         % Note that this only remaps a-z, not accented characters.
  323.       5 index /Widths oget 1 index 7 index /FirstChar get sub oget
  324.       1 string dup 0 5 -1 roll put
  325.         % Stack: font-res font' font' /CharStrings charstrings code
  326.         %   width (x)
  327.       2 index exch dup cvn exch
  328.       dup 0 2 copy get 32 sub put 4 -1 roll {
  329.             % Stack: operand (X) width
  330.         0 setcharwidth exch pop
  331.         currentfont /FontMatrix get matrix invertmatrix concat
  332.         0.7 dup scale 0 0 moveto show
  333.       } /exec cvx 4 packedarray cvx put
  334.     } for put
  335.       } if
  336.       dup /FontName get 2 index ne {
  337.         true .copyfontdict
  338.         2 copy exch /FontName exch put
  339.       } if
  340.       definefont
  341.     } {
  342.         % No descriptor available, use the default algorithm.
  343.       pdfcachefont
  344.     } ifelse
  345.   } ifelse
  346.   exch pop
  347. } bdef
  348.  
  349. % ---------------- Type 1 fonts ---------------- %
  350.  
  351. /buildType1        % <Type1-font-resource> buildType1 <font>
  352.  { dup /BaseFont get pdffindfont
  353.  } bdef
  354.  
  355. % The state dictionary for the embedded Type 1 font reading procedure
  356. % has the following keys and values:
  357. %    data - stream (filter)
  358. %    buffer, buffer2 - string
  359. %    hexify - procedure to convert buffer to hex if needed
  360. %    leftstr - string containing (non-negative) integer
  361. %    sectionstr - string containing a character 0 .. 3
  362. %    stream - (stream) dictionary
  363. %    proc - procedure of the form {-dict- type1read}
  364. %       pfbhdr - string containing 16#80 if PFB, 0 otherwise
  365. % When the procedure is executing, this dictionary is current.
  366. % leftstr and sectionstr are strings so that we can change their values
  367. % reliably in case the font executes a restore!
  368. % We also have to do something special about embedded fonts that
  369. % execute definefont more than once -- that is the function of topFontDict.
  370.  
  371. % Read an embedded Type 1 font.
  372. /readfontfilter {    % <proc> readfontfilter <filter>
  373.   0 () /SubFileDecode filter
  374. } bdef
  375. /readtype1dict 5 dict dup begin
  376.   /definefont {
  377.     dup topFontDict eq topFontDict null eq or {
  378.       dup wcheck not { dup length dict copy } if
  379.       exch pop savedFontName exch
  380.     } if
  381.     //systemdict /definefont get exec
  382.   } bdef
  383.   /eexec {
  384.     % Assume the font dictionary is directly below the file on the stack
  385.     count 0 gt { /topFontDict 2 index cvlit store } if
  386.     //.eexec_param_dict /eexecDecode filter
  387.     //systemdict begin readtype1dictcopy begin cvx stopped
  388.     currentdict readtype1dictcopy eq { end } if
  389.     currentdict //systemdict eq { end } if
  390.      { stop } if
  391.   } bdef
  392. end readonly def
  393. /readtype1 {        % <font-resource> <stream-dict> readtype1 <font>
  394.         % Read the definition, using a procedure-based filter
  395.         % that turns binary/hex conversion on and off
  396.         % at the right times.
  397.    1 index exch
  398.    PDFfile fileposition 3 1 roll
  399.    11 dict begin
  400.      /leftstr (          ) 10 string copy def
  401.        dup /Length1 oget leftstr cvs pop
  402.      /sectionstr <00> 1 string copy def
  403.      /pfbhdr <00> 1 string copy def
  404.      /stream 1 index def
  405.      true resolvestream /data exch def
  406.      /buffer 1000 string def        % arbitrary
  407.      /buffer2 buffer length 2.1 div cvi 1 sub string def
  408.      /hexify /buf2hex load def
  409.    currentdict end
  410.    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  411.    readfontfilter
  412.         % Some buggy embedded fonts leave extra junk on the stack,
  413.         % so we have to make a closure that records the stack depth
  414.         % in a fail-safe way.
  415.    //systemdict begin
  416.         % The PDF specification is somewhat muddy about whether
  417.         % an embedded font's name is supposed to be the BaseFont
  418.         % from the Font object or the FontName from the descriptor.
  419.         % Acrobat Distiller requires the former.  Save away the
  420.         % name so we can substitute it at definefont time.
  421.    //readtype1dict dup length 3 add dict copy begin
  422.    1 index /BaseFont oget /savedFontName exch def
  423.    /topFontDict null def
  424.    /readtype1dictcopy currentdict def
  425.     { run } aload pop count 1 sub 2 packedarray cvx exec
  426.    end end
  427.    count exch sub { pop } repeat
  428.    PDFfile 3 -1 roll setfileposition
  429.    /BaseFont oget findfont
  430.    exch pop
  431.  } bdef
  432.  
  433. % Execute the appropriate reading procedure.
  434. /type1read        % <dict> type1read <string>
  435.  { begin leftstr cvi
  436.     { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  437.    (          ) leftstr copy cvs pop end
  438.  } bdef
  439.  
  440. % Read the next block of data into the buffer.
  441. /type1readdata        % <left> <buffer> type1readdata <substring> <left'>
  442.  { 0 2 index 2 index length .min getinterval
  443.         % Adobe requires readstring to signal an error if given
  444.         % an empty string.  Work around this nonsense here.
  445.    dup length 0 ne { data exch readstring pop } if
  446.    dup length 3 -1 roll exch sub
  447.    DEBUG
  448.     { dup =only ( read ) print
  449.       1 index length =only (: ) print
  450.       1 index == flush
  451.     } if
  452.  } bdef
  453.  
  454. % Read the initial byte to see if we need to skip a 6 byte PFB header
  455. /type1read0 {         % <left> type1read0 <string> <left'>
  456.   sectionstr 0 1 put    % either way we go to the next stage
  457.   pfbhdr type1readdata
  458.   1 index 0 get 16#80 eq {
  459.     (   **** Warning: Embedded Type1 font in PFB format is not valid PDF.\n)
  460.     pdfformaterror
  461.     DEBUG { (skipping PFB header) = flush } if
  462.     exch pop buffer 0 5 getinterval type1readdata exch
  463.     dup 4 get 256 mul 1 index 3 get add 256 mul
  464.     1 index 2 get add 256 mul 1 index 1 get add
  465.     DEBUG { (PFB segment length = ) print dup = } if
  466.     exch pop  % discard the string keeping the PFB segment length
  467.     2 copy ne {
  468.       (   **** Warning: Type 1 PFB segment length and Length 1 value do not match.\n)
  469.       pdfformaterror
  470.       exch     % keep the PFB length instead
  471.     } if
  472.     pop
  473.     buffer type1readdata    % go ahead and read a block
  474.   }
  475.   if    % if not PFB, return pfbhdr string (first char of file, usually %).
  476. } bdef
  477.  
  478. % Read the next block of the initial text portion.
  479. /type1read1 {        % <left> type1read1 <string> <left'>
  480.   DEBUG { (read1 ) print } if
  481.   dup 0 eq {
  482.     pop sectionstr 0 2 put
  483.     stream /Length2 oget
  484.             % Determine whether to hexify data for eexec.
  485.     dup 8 lt {
  486.       type1read2    % Hexify.
  487.     } {
  488.       DEBUG { (read2 ) print } if
  489.       pfbhdr 0 get 16#80 eq {
  490.         % eat 6 more bytes of PFB junk before proceeding
  491.     DEBUG { (skipping PFB header in segment 2) = flush } if
  492.     buffer 0 6 getinterval type1readdata exch
  493.         dup 5 get 256 mul 1 index 4 get add 256 mul
  494.     1 index 3 get add 256 mul 1 index 2 get add
  495.         DEBUG { (PFB segment length = ) print dup = } if
  496.     exch pop  % discard the string keeping the PFB segment length
  497.     2 copy ne {
  498.           (   **** Warning: Type 1 PFB segment length and Length 2 value do not match.\n)
  499.           pdfformaterror
  500.       exch         % keep the PFB length instead
  501.     } if
  502.       pop
  503.       } if
  504.       buffer2 type1readdata exch
  505.             % The check doesn't have to be 100% accurate:
  506.             % hexifying is always OK.
  507.       dup 0 8 getinterval 0 exch { or } forall
  508.       128 ge {
  509.     /hexify { } store
  510.     /buffer2 buffer def    % We don't need an intermediate buffer.
  511.       } if hexify exch
  512.     } ifelse
  513.   } {
  514.     buffer type1readdata
  515.   } ifelse
  516. } bdef
  517.  
  518. % Convert a string from binary to hex for eexec.
  519. % Free variables: buffer.
  520. /buf2hex {        % <string> buf2hex <hexstring>
  521.   buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  522.   buffer (>) search pop exch pop exch pop
  523. } bdef
  524.  
  525. % Read the next block of the encrypted portion.
  526. /type1trailer
  527. (0000000000000000000000000000000000000000000000000000000000000000\n\
  528. 0000000000000000000000000000000000000000000000000000000000000000\n\
  529. 0000000000000000000000000000000000000000000000000000000000000000\n\
  530. 0000000000000000000000000000000000000000000000000000000000000000\n\
  531. 0000000000000000000000000000000000000000000000000000000000000000\n\
  532. 0000000000000000000000000000000000000000000000000000000000000000\n\
  533. 0000000000000000000000000000000000000000000000000000000000000000\n\
  534. 0000000000000000000000000000000000000000000000000000000000000000\n\
  535. cleartomark\n)
  536. readonly def
  537. /type1read2 {        % <left> type1read2 <string> <left'>
  538.   DEBUG { (read2 ) print } if
  539.    dup 0 eq
  540.     { pop sectionstr 0 3 put
  541.       stream /Length3 oget
  542.       dup 0 eq
  543.        { DEBUG { (trailer ) print } if
  544.      type1trailer exch
  545.        }
  546.        { 
  547.          pfbhdr 0 get 16#80 eq {
  548.            % eat 6 more bytes of PFB junk before proceeding
  549.        DEBUG { (skipping PFB header in segment 3) = flush } if
  550.        buffer 0 6 getinterval type1readdata exch
  551.            dup 5 get 256 mul 1 index 4 get add 256 mul
  552.        1 index 3 get add 256 mul 1 index 2 get add
  553.            DEBUG { (PFB segment length = ) print dup = } if
  554.        exch pop  % discard the string keeping the PFB segment length
  555.        2 copy ne {
  556.            (   **** Warning: Type 1 PFB segment length and Length 3 value do not match.\n)
  557.            pdfformaterror
  558.          exch     % keep the PFB length instead
  559.        } if
  560.        pop
  561.          } if
  562.          type1read3
  563.        }
  564.       ifelse
  565.     }
  566.     { buffer2 type1readdata exch hexify exch
  567.     }
  568.    ifelse
  569. } bdef
  570.  
  571. % Read the next block of the final text portion.
  572. % When finished, this procedure returns an empty string.
  573. /type1read3        % <left> type1read3 <string> <left'>
  574.  { DEBUG { (read3 ) print } if
  575.    buffer type1readdata
  576.  } bdef
  577.  
  578. % ---------------- Type 3 fonts ---------------- %
  579.  
  580. /buildType3 {        % <Type3-font-resource> buildType3 <font>
  581.   8 dict begin
  582.     /FontType 3 def
  583.     /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
  584.     /FontBBox 1 index /FontBBox get cvx def
  585.     /FontMatrix 1 index /FontMatrix oget def
  586.     /CharProcs 1 index /CharProcs oget def
  587.     1 index /Widths knownoget {
  588.       /Widths exch def
  589.       /FirstChar 1 index /FirstChar oget def
  590.       /LastChar 1 index /LastChar oget def
  591.     } if
  592.     /FontName 1 index /Name .knownget not { 
  593.        PDFfile fileposition 16 10 string cvrs cvn
  594.     } if def
  595.  
  596.     /Encoding .notdefEncoding 2 index getencoding def
  597.         % We have to define BuildChar rather than BuildGlyph:
  598.         % there is no PDF equivalent of glyphshow, and we need
  599.         % the character code to access the Widths.
  600.     /BuildChar {
  601.         % Stack: font charcode
  602.       1 index begin 3 dict begin
  603.       /Font 3 -1 roll def /CharCode 1 index def
  604.       % Make unknown characters map to /.notdef
  605.       Encoding exch get dup CharProcs exch known
  606.         { CharProcs exch oget }
  607.     { pop CharProcs /.notdef oget }
  608.       ifelse
  609.       PDFfile fileposition exch
  610.       false resolvestream
  611.         % Stack: filepos stream
  612.         % Don't let setgcolor set the color inside the BuildGlyph
  613.         % procedure, because this causes an /undefined error.
  614.       q null /FillColor gput null /StrokeColor gput
  615.       Font /Resources get exch pdfopdict .pdfruncontext
  616.       Q
  617.       PDFfile exch setfileposition
  618.       end end
  619.     } bdef
  620.     FontName currentdict end definefont exch pop
  621. } bdef
  622. /.adjustcharwidth {    % <wx> <wy> .adjustcharwidth <wx'> <wy'>
  623.   /Widths where {
  624.     begin
  625.     CharCode FirstChar ge CharCode LastChar le and {
  626.       exch pop Widths CharCode FirstChar sub get exch
  627.     } if end
  628.   } if
  629. } bdef
  630.  
  631. % ---------------- TrueType fonts ---------------- %
  632.  
  633. /TTfonts mark
  634.   /Arial /Helvetica
  635.   /Arial,Italic /Helvetica-Oblique
  636.   /Arial,Bold /Helvetica-Bold
  637.   /Arial,BoldItalic /Helvetica-BoldOblique
  638.   /CourierNew /Courier
  639.   /CourierNew,Bold /Courier-Bold
  640.   /TimesNewRoman /Times-Roman
  641.   /TimesNewRoman,Italic /Times-Italic
  642.   /TimesNewRoman,Bold /Times-Bold
  643.   /TimesNewRoman,BoldItalic /Times-BoldItalic
  644. .dicttomark readonly def
  645.  
  646. /buildTrueType {    % <TrueType-font-resource> buildTrueType <font>
  647.   dup /BaseFont oget
  648.   (   **** Warning: Fonts with Subtype = /TrueType should be embedded.\n) pdfformaterror
  649.   (                 But ) pdfformaterror dup =string cvs pdfformaterror ( is not embedded.\n) pdfformaterror
  650.   dup TTfonts exch .knownget {
  651.     QUIET not {
  652.       (Substituting font ) print dup =only
  653.       ( for ) print 1 index =only (.) = flush
  654.     } if
  655.     exch 3 1 roll pdffindfont
  656.     true .copyfontdict
  657.     2 copy exch /FontName exch put
  658.     definefont
  659.   } {
  660.     pdffindfont
  661.   } ifelse
  662. } bdef
  663.  
  664. % Read an embedded TrueType font.
  665. /readtruetype {        % <font-resource> <stream-dict> readtruetype <font>
  666.         % This is much simpler than readtype1, because we don't
  667.         % have to deal with the tripartite .PFB format.
  668.   1 index exch
  669.   PDFfile fileposition 3 1 roll
  670.   true resolvestream readfontfilter
  671.         % Stack: filepos fontres stream
  672.   1 index /Subtype get /CIDFontType2 eq {
  673.     .loadttcidfont
  674.         % Stack: filepos fontres cidfont
  675.     1 index /CIDToGIDMap knownoget {
  676.       dup /Identity eq {
  677.     pop
  678.       } {
  679.     true resolvestream
  680.         % Stack: filepos fontres font mapstream
  681.     dup 2 index /CIDCount oget dup 32767 le {
  682.           2 mul string readstring pop
  683.         } {
  684.       % Length exceeded max string size, use an array of two strings
  685.           % stack: filepos fontres font mapstream mapstream CIDCount
  686.           1 index 32767 string readstring not {
  687.             (   **** Warning: CIDToGIDMap length of ) pdfformaterror
  688.             dup length 2 div cvi =string cvs pdfformaterror
  689.             (, expected length of ) pdfformaterror
  690.             exch =string cvs pdfformaterror
  691.             (.\n) pdfformaterror
  692.             exch pop
  693.           } {
  694.         3 1 roll 32767 sub string readstring pop 
  695.         2 array astore
  696.           } ifelse
  697.         } ifelse
  698.     exch closefile exch dup length 5 add dict .copydict
  699.     dup /FID undef
  700.     dup /CIDMap 4 -1 roll put
  701.     dup /CIDFontName get exch /CIDFont defineresource
  702.       } ifelse
  703.     } if
  704.   } {
  705.     1 index /FontDescriptor oget /Flags get 4 and 0 ne % is_symbolic
  706.     .loadpdfttfont
  707.   } ifelse
  708.   exch pop
  709.   PDFfile 3 -1 roll setfileposition
  710.         % Ignore both the Encoding and the Widths.
  711.   exch pop
  712. } bdef
  713.  
  714. % ---------------- Type 0 fonts ---------------- %
  715.  
  716. % Predefine the known CMaps, but only create them on demand.
  717. /knownCMaps mark
  718.   /Identity-H { /Identity-H 0 makeIdentityCMap }
  719.   /Identity-V { /Identity-V 1 makeIdentityCMap }
  720. .dicttomark def
  721.  
  722. /makeIdentityCMap {        % <cmapname> <wmode> .makeIdentityCMap -
  723.   .currentglobal true .setglobal 3 1 roll
  724.   /CIDInit /ProcSet findresource begin
  725.   12 dict begin
  726.     begincmap
  727.     /WMode exch def
  728.     /CMapName exch def
  729.     /CIDSystemInfo 3 dict dup begin
  730.       /Registry (Adobe) def
  731.       /Ordering (Identity) def
  732.       /Supplement 0 def
  733.     end def
  734.     %/CMapName (see above)
  735.     /CMapVersion 1 def
  736.     /CMapType 1 def
  737.     %WMode (see above)
  738.     % The PDF documentation says that these CMaps map CIDs
  739.     % "1 to 65,536".  This is a misprint for 0 to 65,535.
  740.     1 begincodespacerange
  741.     % <0001> <00ff>  <0100> <ffff>
  742.       <0000> <ffff>
  743.     endcodespacerange
  744.     1 begincidrange
  745.     % <0001> <00ff> 1   <0100> <ffff> 256
  746.       <0000> <ffff> 0
  747.     endcidrange
  748.     endcmap
  749.     CMapName currentdict /CMap defineresource
  750.     knownCMaps CMapName 2 index put
  751.   end        % CMap
  752.   end        % CIDInit ProcSet
  753.   exch .setglobal
  754. } bdef
  755.  
  756. /buildType0 {        % <Type0-font-resource> buildType0 <font>
  757.   dup /BaseFont get    % FontName
  758.   1 index /Encoding oget
  759.   dup type /nametype eq {
  760.     dup /CMap resourcestatus {
  761.     pop pop /CMap findresource
  762.     } {
  763.     knownCMaps 1 index .knownget
  764.       { exch pop exec } { /undefined signalerror } ifelse
  765.     } ifelse
  766.   } {
  767.     PDFfile fileposition exch
  768.     dup /CMapName get exch true resolvestream cvx exec
  769.     /CMap findresource
  770.     exch PDFfile exch setfileposition
  771.   } ifelse        % CMap
  772.   [
  773.     3 index /DescendantFonts oget { exec resourcefont } forall
  774.   ]            % subfonts
  775.   composefont
  776.         % Stack: fontres font
  777.   1 index /FontMatrix knownoget {
  778.     dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
  779.       1 index exch makefont exch /FontName get exch definefont
  780.     } {
  781.       pop
  782.     } ifelse
  783.   } if exch pop
  784. } bdef
  785.  
  786. % ---------------- CIDFontType0/2 fonts ---------------- %
  787.  
  788. % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
  789. % arrays and using a (currently very inefficient) CDevProc.
  790. % For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts".
  791. % It notes default DW is 0, but Acrobat Reader uses 1000 as default.
  792. % If DW is 0, currentpoint does not move by default in rendering text
  793. % horizontally, the result is unreadable. You can check it by Acrobat.
  794.  
  795. /.pdfDefaultDW  1000 def
  796. /.pdfDefaultDW2 [ 880 -1000 ] def
  797.  
  798. /addCIDmetrics {    % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  799.   dup length 5 add dict .copydict
  800.   dup /FID undef
  801.   dup /UniqueID undef
  802.   dup /XUID undef
  803.     % Insert the widths into the font.
  804.  
  805.         % Stack: pdfresource newfont
  806.  
  807.   1 index /DW .knownget {
  808.     1 index /DW 3 -1 roll put
  809.   } {
  810.     dup /DW .pdfDefaultDW put
  811.   } ifelse
  812.  
  813.   1 index /W .knownget {
  814.     dup 2 index /W 3 -1 roll put
  815.     .pdfMakeInternalW 1 index /.internalW 3 -1 roll put
  816.   } if
  817.  
  818.   1 index /DW2 .knownget {
  819.     1 index /DW2 3 -1 roll put
  820.   } {
  821.     dup /DW2 .pdfDefaultDW2 put
  822.   } ifelse
  823.  
  824.   1 index /W2 .knownget {
  825.     dup 2 index /W2 3 -1 roll put
  826.     .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
  827.   } if
  828.  
  829.   dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  830.   exch pop
  831. } bdef
  832.  
  833. /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
  834.  
  835.   % convert /W or /W2 to internal expression
  836.   %
  837.   %   mtx_array: original /W or /W2 array
  838.   %   item_size: number of metrics values per CID
  839.   %
  840.   %   for detail of the metrics list format in PDF,
  841.   %   refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
  842.   % 
  843.   %   format of single entry in internal expression
  844.   %
  845.   %     [
  846.   %       [cid_begin cid_end]
  847.   %       value_is_varied (bool)
  848.   %       [ [values for cid_begin...]
  849.   %         [values for cid_begin + 1]
  850.   %         ... ]
  851.   %     ]
  852.   %
  853.  
  854.   7 dict
  855.   begin
  856.     /itemSize exch def
  857.     /M exch def            % original /W or /W2
  858.     /Msize M length def
  859.     /Mi { M i get } def        % W[i]
  860.     /Mi1 { M i 1 add get } def    % W[i + 1]
  861.     /putMTXEntry <<
  862.       /arraytype   {
  863.          [
  864.            [Mi Mi Mi1 length add 1 sub]
  865.            true
  866.            [
  867.              0 itemSize Mi1 length 1 sub {
  868.                [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
  869.              } for
  870.            ]
  871.          ]
  872.          /i i 2 add def
  873.       }
  874.       /integertype {
  875.          [
  876.            [Mi Mi1]
  877.            false
  878.            [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
  879.          ]
  880.          /i i 3 add def
  881.       }
  882.     >> def
  883.  
  884.     /i 0 def
  885.  
  886.     [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
  887.   end
  888. } def
  889.  
  890. /.pdfMakeInternalW  { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
  891. /.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
  892.  
  893. /.pdfGetMTXByCID { % <internalMTXArray> <cid>
  894.                    %     .pdfGetMTXByCID
  895.                    %         { <MTXEntry> true | false }
  896.  
  897.   % get values for given CID from internal format of /W or /W2
  898.  
  899.   exch
  900.   {
  901.     {
  902.       dup 0 get {} forall      % Stack: <cid> <entry> <cid_0> <cid_1>
  903.       3 index lt { pop pop false exit } if
  904.       2 index exch sub dup 0 lt { pop pop false exit } if
  905.       1 index 1 get not { pop 0 } if
  906.       exch 2 get exch get true exit
  907.     } loop
  908.     { exit } if
  909.   } forall
  910.   dup type /arraytype eq { exch pop true } { pop false } ifelse
  911. } def
  912.  
  913.  
  914. % Apply the [D]W[2] metrics to a character before displaying.
  915. /CIDWProc {        % <w0x> <w0y> <llx> <lly> <urx> <ury>
  916.             %   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
  917.             %   <w0x'> ... <vy'>
  918.  
  919.   begin % push <font> to currentdict
  920.     % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
  921.     5 1 roll pop pop pop pop
  922.  
  923.     {
  924.       currentdict /DW .knownget not {   % no DW
  925.         .pdfDefaultDW exit              % replace <w0x> by defaultDW
  926.       } if
  927.  
  928.       currentdict /.internalW .knownget not {    % no W
  929.         exit                            % use already-stacked DW
  930.       } if
  931.  
  932.       dup length 0 eq {                 % W is null array
  933.         pop                             % discard unusable W
  934.         exit                            % use already-stacked DW
  935.       } if
  936.  
  937.       % W is finite array, try to get W_cid
  938.       2 index .pdfGetMTXByCID {           % got W, discard DW
  939.         exch pop {} forall
  940.         exit
  941.       } if
  942.  
  943.       exit
  944.     } loop
  945.  
  946.     1000 div                    % <w0x'> (normalized W)
  947.     0                           % <w0y'>
  948.  
  949.     % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
  950.     9 -2 roll pop pop           % discard <w0x> <w0y>
  951.     7  2 roll                   % put <w0x'> <w0y'>
  952.  
  953.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
  954.     0                           % <w1x'>
  955.     exch                        % put <w1x'>
  956.  
  957.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
  958.     {
  959.       currentdict /DW2 .knownget not {  % no DW2, use defaultDW2
  960.         .pdfDefaultDW2 exit
  961.       } if
  962.  
  963.       currentdict /.internalW2 .knownget not {   % has DW2, no W2
  964.         exit                            % use already-stacked DW2
  965.       } if
  966.  
  967.       dup length 0 eq {                 % W2 is null array
  968.         pop                             % discard unusable W2
  969.         exit                            % use already-stacked DW2
  970.       } if
  971.  
  972.       2 index .pdfGetMTXByCID {        % got W2_cid, discard DW2
  973.         exch pop
  974.         exit
  975.       } if
  976.  
  977.       % could not get W2_cid
  978.       exit
  979.  
  980.     } loop
  981.  
  982.     exch pop                            % discard <cid>
  983.  
  984.  
  985.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
  986.     dup length 2 eq {                   % this is DW2
  987.       {1000 div} forall exch
  988.       4 index 7 index add 2 div         % <vx'> = (<urx> + <llx>) / 2
  989.       exch
  990.     }{                                  % assume W2
  991.       {1000 div} forall
  992.     } ifelse
  993.   end                                   % recover currentdict
  994.  
  995. } def
  996.  
  997. % <string> <match> tailmatch ==> <pre> true
  998. %                            ==> <string> false
  999. /tailmatch {
  1000.   2 copy length 1 index length .min
  1001.   dup 2 index length exch sub exch getinterval
  1002.   1 index eq {
  1003.     length 1 index length exch sub
  1004.     0 exch getinterval true
  1005.   } {
  1006.     pop false
  1007.   } ifelse
  1008. } bind def
  1009.  
  1010. /makeboldfont {
  1011.   16 dict begin
  1012.     /strokewidth exch def
  1013.     /basecidfont exch def
  1014.     /FontMatrix [ 1 0 0 1 0 0 ] def
  1015.  
  1016.     /CIDFontName /.boldfont def
  1017.     /CIDFontType 1 def
  1018.  
  1019.     /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
  1020.     /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
  1021.  
  1022.     /CIDSystemInfo dup basecidfont exch get def
  1023.     /FontBBox [ basecidfont /FontBBox get cvx exec
  1024.       4 2 roll basecidfont /FontMatrix get transform
  1025.       4 2 roll basecidfont /FontMatrix get transform
  1026.     ] def
  1027.  
  1028.     /tmpstr 2 string def
  1029.     /BuildGlyph {
  1030.       gsave
  1031.       exch begin
  1032.         dup 256 idiv tmpstr exch 0 exch put
  1033.         256 mod tmpstr exch 1 exch put
  1034.         rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
  1035.         { basefont-V } { basefont-H } ifelse setfont
  1036.         strokewidth setlinewidth
  1037.         1 setlinejoin
  1038.         newpath
  1039.         0 0 moveto tmpstr false charpath stroke
  1040.         0 0 moveto tmpstr show
  1041.         currentpoint setcharwidth
  1042.       end
  1043.       grestore
  1044.     } bind def
  1045.  
  1046.    currentdict
  1047.   end
  1048.   dup /CIDFontName get exch /CIDFont defineresource
  1049. } bind def
  1050.  
  1051. % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
  1052. %   CIDFont-resource is not modified.
  1053. /findCIDFont {
  1054.   {
  1055.     dup /CIDFont resourcestatus {
  1056.       pop pop /CIDFont findresource
  1057.       exit
  1058.     } if
  1059.  
  1060.     dup dup length string cvs
  1061.     (,Bold) tailmatch {
  1062.       exch pop
  1063.       cvn findCIDFont 0.03 makeboldfont
  1064.       exit
  1065.     } if
  1066.     (,Italic) tailmatch {
  1067.       exch pop
  1068.       cvn findCIDFont
  1069.       [ 1 0 0.3 1 0 0 ] makefont
  1070.       exit
  1071.     } if
  1072.     (,BoldItalic) tailmatch {
  1073.       exch pop
  1074.       cvn findCIDFont 0.03 makeboldfont
  1075.       [ 1 0 0.3 1 0 0 ] makefont
  1076.       exit
  1077.     } if
  1078.     pop
  1079.  
  1080.     1 index /CIDSystemInfo get begin Registry (-) Ordering end
  1081.     concatstrings concatstrings
  1082.     cvn
  1083.     QUIET not {
  1084.       (Substituting ) print dup ==only
  1085.       ( for ) print 1 index ==only (.\n) print
  1086.     } if
  1087.     exch pop
  1088.     /CIDFont findresource
  1089.     exit
  1090.   } loop
  1091. } bdef
  1092.  
  1093. /buildCIDType0 {    % <CIDFontType0-font-resource> buildCIDType0 <font>
  1094.   dup /BaseFont get exch 1 index findCIDFont
  1095.   addCIDmetrics /CIDFont defineresource
  1096. } bdef
  1097.  
  1098. /buildCIDType2 {    % <CIDFontType2-font-resource> buildCIDType2 <font>
  1099.   dup /BaseFont get exch 1 index findCIDFont
  1100.   addCIDmetrics /CIDFont defineresource
  1101. } bdef
  1102.  
  1103. % ---------------- Other embedded fonts ---------------- %
  1104.  
  1105. /fontloadprocs mark
  1106.   /Type1C /readType1C cvx
  1107.   /CIDFontType0C /readCIDFontType0C cvx
  1108. .dicttomark readonly def
  1109.  
  1110. % Read an embedded compressed font.
  1111. /readType1C {        % <font-resource> <stream-dict> readType1C <font>
  1112.   1 index exch
  1113.   PDFfile fileposition 3 1 roll
  1114.   dup true resolvestream dup readfontfilter
  1115.         % Stack: pos resource streamdict stream filter
  1116.   3 index /FontDescriptor oget /FontName oget
  1117.   1 index FRD
  1118.   closefile closefile pop
  1119.   PDFfile 3 -1 roll setfileposition
  1120.   /FontDescriptor oget /FontName oget findfont
  1121.   exch pop
  1122. } bdef
  1123.  
  1124. % Read an embedded CFF CIDFont.
  1125. /readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
  1126.   PDFfile fileposition 3 1 roll
  1127.   dup true resolvestream dup readfontfilter
  1128.         % Stack: pos resource streamdict stream filter
  1129.   3 index /FontDescriptor oget /FontName oget
  1130.   1 index FRD
  1131.   closefile closefile pop
  1132.   PDFfile 3 -1 roll setfileposition
  1133.         % Some broken Adobe software produces PDF files in which
  1134.         % the FontName of the CFF font and the FontName in the
  1135.         % FontDescriptor don't match the BaseFont in the font.
  1136.         % Use the FontName, rather than the BaseFont, here.
  1137.   dup /FontDescriptor oget /FontName oget /CIDFont findresource
  1138.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  1139. } bdef
  1140.  
  1141. % ---------------- Font lookup ---------------- %
  1142.  
  1143. /fonttypeprocs mark        % <font-resource> -proc- <font>
  1144.   /Type0 /buildType0 cvx
  1145.   /Type1 /buildType1 cvx
  1146.   /MMType1 1 index
  1147.   /Type3 /buildType3 cvx
  1148.   /TrueType /buildTrueType cvx
  1149.   /CIDFontType0 /buildCIDType0 cvx
  1150.   /CIDFontType2 /buildCIDType2 cvx
  1151. .dicttomark readonly def
  1152.  
  1153. /adjustfonttypes mark
  1154.   /Type1 true
  1155.   /MMType1 true
  1156.   /TrueType true
  1157. .dicttomark readonly def
  1158.  
  1159. /resourcefont            % <font-resource> resourcefont <font>
  1160. { dup /PSFont .knownget
  1161.   { /FID knownoget { type /fonttype eq } { //false } ifelse }
  1162.   { //false }
  1163.   ifelse
  1164.   { /PSFont get }
  1165.   { dup dup /FontDescriptor knownoget {    % Stack: font-res font-res font-desc
  1166.       dup /FontObject .knownget {
  1167.     3 1 roll pop pop
  1168.       } {
  1169.     dup /FontFile knownoget
  1170.     { exch pop readtype1 }
  1171.     { dup /FontFile2 knownoget
  1172.       { exch pop readtruetype }
  1173.       { /FontFile3 knownoget
  1174.         { dup /Subtype get fontloadprocs exch get exec }
  1175.             { dup /Subtype get fonttypeprocs exch get exec }
  1176.         ifelse
  1177.       }
  1178.       ifelse
  1179.     }
  1180.     ifelse
  1181.     1 index /FontDescriptor oget
  1182.     1 index /FontObject exch put        % Save pointer to the font
  1183.       }
  1184.       ifelse
  1185.     }
  1186.     { dup /Subtype get fonttypeprocs exch get exec }
  1187.     ifelse
  1188.     % Stack: font-res font
  1189.     1 index 3 1 roll
  1190.     1 index /Subtype get
  1191.     //adjustfonttypes exch known { adjustfont } { exch pop } ifelse
  1192.     dup 3 1 roll /PSFont exch put
  1193.   }
  1194.   ifelse
  1195. } bdef
  1196.  
  1197. drawopdict begin
  1198.   /d0 {
  1199.     .adjustcharwidth setcharwidth
  1200.   } bdef
  1201.   /d1 {
  1202.     4 index 0 ne {
  1203.       % invalid wy parameter for d1 in Type3 font (must be 0)
  1204.       % Even though the PDF 1.4 specification states that this must be 0,
  1205.       % Distiller sometimes creates Type3 fonts with non-zero wy. We set
  1206.       % it to 0 since this is apparently what Acrobat Reader 4 and 5 do,
  1207.       % but if the specification is ever changed to allow non-zero wy, this
  1208.       % will not work.
  1209.       5 -1 roll pop 0 5 1 roll    % set wy to 0
  1210.     } if
  1211.     6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
  1212.   } bdef
  1213.   /Tf {
  1214.     1 index Page /Font rget not { 1 index /invalidfont signalerror } if
  1215.     resourcefont exch Tf pop
  1216.   } bdef
  1217. end
  1218.  
  1219. end            % pdfdict
  1220. end            % GS_PDF_ProcSet
  1221. .setglobal
  1222.